package com.ywd.platform.netty.jt080.util;

import java.util.HashMap;
import java.util.Map;

/**
 * JT808 消息体属性处理工具类
 */
public class JT808BodyPropsUtil {

    // 消息体属性位掩码常量
    private static final int BODY_LENGTH_MASK = 0x03FF;  // 低10位：消息体长度
    private static final int VERSION_FLAG_MASK = 0x0400; // 第10位：版本标识（2013/2019版协议标识）
    private static final int ENCRYPTION_MASK = 0x3800;   // 第11-13位：加密方式
    private static final int SUB_PACKAGE_MASK = 0x4000;  // 第14位：分包标志
    private static final int PROTOCOL_VERSION_MASK = 0x8000; // 第15位：协议版本标识（2019版协议特有）

    // 加密方式常量
    public static final int ENCRYPTION_NONE = 0; // 不加密
    public static final int ENCRYPTION_RSA = 1;  // RSA加密
    public static final int ENCRYPTION_AES = 2;  // AES加密
    public static final int ENCRYPTION_RESERVED = 3; // 保留

    /**
     * 构建JT808-2019协议消息体属性值
     *
     * @param bodyLength 消息体长度 (0-1023字节)
     * @param encryptionType 加密方式 (0-不加密, 1-RSA, 2-AES, 3-保留)
     * @param hasSubPackage 是否有分包
     * * @param isJtt2019Protocol 是否为JTT2019协议（bit14）
     * @return 消息体属性值 (16位无符号short)
     * @throws IllegalArgumentException 参数无效
     */
    public static short buildBodyProps2019(int bodyLength, int encryptionType,
                                           boolean hasSubPackage, boolean isJtt2019Protocol) {
        // 验证参数
        if (bodyLength < 0 || bodyLength > 1023) {
            throw new IllegalArgumentException("消息体长度必须在0-1023之间");
        }
        if (encryptionType < 0 || encryptionType > 3) {
            throw new IllegalArgumentException("加密方式必须在0-3之间");
        }

        int props = 0;

        // bit0~bit9: 消息体长度
        props |= (bodyLength & 0x3FF);

        // bit10~bit12: 加密类型
        props |= ((encryptionType & 0x07) << 10);

        // bit13: 分包标志
        props |= (hasSubPackage ? 1 : 0) << 13;

        // bit14: 协议版本标识 (1=JTT2019)
        props |= (isJtt2019Protocol ? 1 : 0) << 14;

        // bit15: 保留位，必须为0

        return (short) props;
    }

    /**
     * 获取消息体长度
     */
    public static int getBodyLength(short bodyProps) {
        return bodyProps & BODY_LENGTH_MASK;
    }

    /**
     * 是否包含版本标识
     */
    public static boolean hasVersionFlag(short bodyProps) {
        return (bodyProps & VERSION_FLAG_MASK) != 0;
    }

    /**
     * 获取加密方式
     */
    public static int getEncryptionType(short bodyProps) {
        return (bodyProps & ENCRYPTION_MASK) >> 11;
    }

    /**
     * 是否包含分包
     */
    public static boolean hasSubPackage(short bodyProps) {
        return (bodyProps & SUB_PACKAGE_MASK) != 0;
    }

    /**
     * 是否为2019版协议
     */
    public static boolean is2019Protocol(short bodyProps) {
        return (bodyProps & PROTOCOL_VERSION_MASK) != 0;
    }

    /**
     * 解析JT808-2019协议消息体属性值
     */
    public static Map<String, Object> parseBodyProps2019(short bodyProps) {
        Map<String, Object> result = new HashMap<>();

        // 将short转换为无符号int
        int props = bodyProps & 0xFFFF;

        // 提取消息体长度（低10位）
        int bodyLength = props & 0x03FF;
        result.put("bodyLength", bodyLength);

        // 提取版本标识（第10位）
        boolean hasVersionFlag = (props & 0x0400) != 0;
        result.put("hasVersionFlag", hasVersionFlag);

        // 提取加密方式（第11-13位）
        int encryptionType = (props & 0x3800) >> 11;
        String encryptionName;
        switch (encryptionType) {
            case 0: encryptionName = "None"; break;
            case 1: encryptionName = "RSA"; break;
            case 2: encryptionName = "AES"; break;
            default: encryptionName = "Reserved"; break;
        }
        result.put("encryptionType", encryptionName);

        // 提取分包标志（第14位）
        boolean hasSubPackage = (props & 0x4000) != 0;
        result.put("hasSubPackage", hasSubPackage);

        // 提取协议版本标识（第15位，2019版协议特有）
        boolean is2019Protocol = (props & 0x8000) != 0;
        result.put("is2019Protocol", is2019Protocol);

        // 确定协议版本
        String protocolVersion = is2019Protocol ? "JTT2019" : "JTT2013";
        result.put("protocolVersion", protocolVersion);

        return result;
    }

    /**
     * 使用示例
     */
    public static void main(String[] args) {
        // 示例1：构建与解析 0x840B (33803)
        short bodyProps = buildBodyProps2019(11,ENCRYPTION_NONE, false, true);
        System.out.println("构建的消息体属性值: " + (bodyProps & 0xFFFF) + " (0x" + Integer.toHexString(bodyProps & 0xFFFF) + ")");

        Map<String, Object> parsedProps = parseBodyProps2019(bodyProps);
        System.out.println("解析结果:");
        for (Map.Entry<String, Object> entry : parsedProps.entrySet()) {
            System.out.println("  " + entry.getKey() + ": " + entry.getValue());
        }

        System.out.println();

        // 示例2：构建其他属性值
        short bodyProps2 = buildBodyProps2019(256,  ENCRYPTION_RSA, true, true);
        System.out.println("构建的消息体属性值: " + (bodyProps2 & 0xFFFF) + " (0x" + Integer.toHexString(bodyProps2 & 0xFFFF) + ")");

        Map<String, Object> parsedProps2 = parseBodyProps2019(bodyProps2);
        System.out.println("解析结果:");
        for (Map.Entry<String, Object> entry : parsedProps2.entrySet()) {
            System.out.println("  " + entry.getKey() + ": " + entry.getValue());
        }
    }
}
